Universal Serial Bus (USB) is an industry standard that defines the cables, connectors and protocols used for connection, communication and power supply between computers and electronic devices. USB was designed to standardize the connection of computer peripherals, such as keyboards, pointing devices, digital cameras, printers, portable media players, disk drives and network adapters to personal computers, both to communicate and to supply electric power. It was designed not to require specific interrupt or DMA resources, and also to be ‘hot-pluggable’.
A USB host controller (i.e., a USB host, e.g., in a personal computer) communicates with a USB device (e.g., a printer). USB device communication is based on pipes (logical channels). A pipe is a connection from the USB host controller to a logical entity, found on a USB device, and named an endpoint. Each USB device has one or more endpoints. Each endpoint is a source or sink of data. Data may flow OUT from the USB host to a USB device, or IN from the USB device to the USB host. USB devices talk to the USB host through four different types of USB transfers: control, bulk, isochronous, and interrupt transfers.
Isochronous transfers are data transfers at some guaranteed data rate (often, but not necessarily, as fast as possible) but with possible data loss. Error-free delivery is not guaranteed. Isochronous transfers are employed primarily in applications such as audio data streaming, where it is important to maintain the data flow, but not so important if some data is missed or corrupted. An isochronous transfer uses either an IN transaction or an OUT transaction depending on the type of endpoint. The special feature of these transactions is that there is no handshake packet at the end. Isochronous transfers occur continuously and periodically (e.g., 8000 times per second).
Interrupt transfers are data transfers for devices that need guaranteed quick responses (bounded latency). Interrupt transfers are employed to keep up to date of any changes of status in a device. Examples of their use are for a mouse or a keyboard. Traditionally, interrupt requests on microcontrollers are device generated. However, under USB, if a device requires the attention of the USB host, it should wait until the USB host polls it before it can report that it needs urgent attention. An interrupt request is queued by a USB device driver until the USB host polls the USB device asking for data.
Bulk transfers are data transfers used for large bursty data. Examples include a print-job sent to a printer or an image generated from a scanner. Bulk transfers are designed to transfer large amounts of data with error-free delivery, but with no guarantee of bandwidth.
A control transfer is a bi-directional transfer that uses both an IN and an OUT endpoint. Control transfers are typically used for command and status operations and help to set up a USB device. They are typically bursty, random packets which are initiated by the host and use best effort delivery.
Control and bulk transfers do not have critical timing constraints, but isochronous and interrupt transfers typically do. With isochronous transfers, the USB device may need to be read/written to up to 8000 times per second and failing to do so may result in data loss. Normally this is handled by the Operating Systems (OS) USB stack and USB device drivers by queuing a number of packets in a USB host controller and as soon as the transfer has been received and acknowledged (i.e. processed or completed), re-queuing packets.
Packet completion is signaled to the USB stack by a hardware interrupt, guaranteeing that the USB device driver will be acknowledged of packet completion with minimal latency. To minimize latency (e.g. in audio/video streams), the USB device driver queues the minimum number of packets needed to ensure reliable operation, based on the maximum latency of the USB stack and interrupt handling.
These timing constrains become a problem when redirecting USB traffic from a USB device through a virtual machine to a remote client machine over a network to which the USB device is physically connected. The packets first pass through the USB stack in the machine to which the USB device is physically connected before being passed to the USB stack in the virtual machine (i.e., the guest USB stack). This adds to latency, rendering assumptions about worst case latency invalid. When performing USB redirection to a remote client machine over a network, there is also a network latency component, worsening the latency problem. For a USB interrupt transaction corresponding to, for example, a user moving a USB-connected mouse at a remote client location, the user may perceive a noticeable time delay before seeing a corresponding pointer move on their terminal screen. Further, once the USB-connected mouse has a data packet to send to a device driver (virtual or real), e.g., the mouse has moved, a corresponding data packet should be processed (complete). Once an interrupt-related data packet has completed, another data packet needs to be received within a certain time. Failing to receive a new packet may lead to data loss, i.e., some mouse movement or mouse click may be lost.
Conventional remedies for the network latency problem include changing the number of packets that a virtual device driver queues. Unfortunately, this typically requires modifications to the virtual USB device driver, which is undesirable.